<template>
  <div ref="float" class="v-float-container flex-column" :target="state.target" :style="state.fix" id="v-float-container">
    <slot></slot>
  </div>
</template>

<script setup>
  import { ref, reactive, getCurrentInstance, onMounted, onUnmounted, watch, nextTick } from 'vue'

  defineOptions({ name: 'v-float-container' })

  const { proxy } = getCurrentInstance()
  const _this = proxy
  const props = defineProps({
    target: [Object, undefined],
    width: [String, Number],
    height: [String, Number],
  })
  const float = ref(null)
  const state = reactive({
    target: props.target,
    fix: { left: '0px', top: '45px', width: props.width + 'px', height: props.height + 'px' },
  })
  watch(
    () => props.target,
    (value, prevValue) => {
      state.target = value
    }
  )
  watch(
    () => props.modelValue,
    (value, prevValue) => {
      state.visible = value
      handlerVisible(value)
    }
  )
  const handlerVisible = (value) => {
    nextTick(() => {
      if (value) {
        Setfix()
      }
    })
  }
  // 元素相对于body的offsetTop
  const getTop = (el) => {
    let offsetTop = 0
    const pos = el.getBoundingClientRect()
    offsetTop = pos.top + document.documentElement.scrollTop
    /*
  while (el && el.tagName !== 'BODY') {
    offsetTop += el.offsetTop
    el = el.offsetParent
  }
  */
    return offsetTop
  }
  const getLeft = (el) => {
    let offsetLeft = 0
    const pos = el.getBoundingClientRect()
    offsetLeft = pos.left + document.documentElement.scrollLeft
    /*
  while (el && el.tagName !== 'BODY') {
    offsetLeft += el.offsetLeft
    el = el.offsetParent
  }
  */
    return offsetLeft
  }
  const Setfix = () => {
    let left = 0,
      top = 0,
      width = props.width,
      height = props.height
    if (float.value) {
      var winHeight = document.documentElement.offsetHeight //offsetHeight //scrollHeight //clientHeight
      var winWidth = document.documentElement.offsetWidth //offsetWidth //scrollWidth //clientWidth
      //console.log(winHeight,winWidth)
      //var bodyWidth = document.body.offsetWidth;
      //var bodyHeight = document.body.offsetHeight;
      var targetHeight = state.target.offsetHeight
      var targetWidth = state.target.offsetWidth
      //console.log(targetHeight,targetWidth)
      var targetTop = getTop(state.target)
      var targetLeft = getLeft(state.target)

      var floatHeight = float.value.offsetHeight
      var floatWidth = float.value.offsetWidth
      //console.log(floatHeight,floatWidth)
      //console.log(targetTop,(winHeight-targetHeight-targetTop))
      //上下判断
      //1.先判断下方能否装下
      if (winHeight - targetTop - targetHeight > floatHeight) {
        top = targetTop + targetHeight
      } else {
        if (targetTop > winHeight - targetHeight - targetTop) {
          //2.判断位置在上
          if (targetTop < floatHeight) {
            //调整高度
            ;(height = targetTop), (floatHeight = targetTop)
          }
          top = targetTop - floatHeight
        } else {
          //3.判断位置在下
          if (floatHeight > winHeight - targetTop - targetHeight) {
            //调整高度
            height = winHeight - targetTop - targetHeight
          }
          top = targetTop + targetHeight
        }
      }
      //左右判断
      //1.先判断右边是否能装下
      if (winWidth - targetLeft > floatWidth) {
        left = targetLeft
      } else {
        if (winWidth - targetLeft > targetLeft + targetWidth) {
          //往右延伸
          if (winWidth - targetLeft < floatWidth) {
            //宽度高度
            width = winWidth - targetLeft
          }
          left = targetLeft
        } else {
          //往左延伸
          if (targetLeft + targetWidth < floatWidth) {
            //宽度高度
            width = targetLeft + targetWidth
            floatWidth = width
          }
          left = targetLeft - (floatWidth - targetWidth)
        }
      }
    }
    nextTick(() => {
      state.fix = { left: left + 'px', top: top + 'px', width: width + 'px', height: height + 'px' }
    })
  }
  //const emits = defineEmits(['update:modelValue']);
  onMounted(() => {
    nextTick(() => {
      const body = document.querySelector('body')
      Setfix()
      if (body.append) {
        body.append(_this.$el)
      } else {
        body.appendChild(_this.$el)
      }
      window.addEventListener('resize', function () {
        Setfix()
      })
    })
  })

  onUnmounted(() => {})
</script>

<style scoped rel="stylesheet/scss" lang="scss">
  .v-float-container {
    background-color: #fff;
    position: absolute;
    z-index: 100;
    box-shadow: 0px 0px 4px rgb(0 0 0 / 35%);
    border-radius: 4px;
  }
</style>
